package com.kcht.rfid.rd30.secretary.dispatch.impl.operation;

import com.google.protobuf.InvalidProtocolBufferException;
import com.kcht.rfid.rd30.secretary.core.command.*;
import com.kcht.rfid.rd30.secretary.core.common.Rd30Configuration;
import com.kcht.rfid.rd30.secretary.dispatch.IReaderChannel;
import lombok.extern.slf4j.Slf4j;
import uhf_msg.Uhf;

import java.util.Observable;
import java.util.Observer;
import java.util.Random;

/**
 * 模板方法，规范操作流程
 */
@Slf4j
public abstract class BaseOperation extends Observable {

    public BaseOperation(Observer observer){
        this.addObserver(observer);
    }
    /**
     * 处理操作
     */
    protected abstract void handlerOperation(IReaderChannel channel, uhf_msg.Uhf.uhf_response response, Integer antId, BasicReaderCommand command);

    /**
     *
     * InventQuery返回状态为1时调用
     * */
    protected void handlerQuery1(String ip, int antId, uhf_msg.Uhf.uhf_response queryResponse, BasicReaderCommand command) {
        log.error("发送{}指令@InventQuery时出错,NEXT:@InventRepeat--->ip:{},天线接口:{},返回状态:1",getOperation(command),ip,antId);
    }

    /**
     * 未清点到标签
     * */
    protected void handlerQuery2(String ip, int antId, uhf_msg.Uhf.uhf_response queryResponse, BasicReaderCommand command) {
        log.error("发送{}指令@InventQuery未检测到标签,End--->ip:{},天线接口:{},返回状态:1",getOperation(command),ip,antId);
    }

    protected void handlerQueryOther(String ip, int antId, uhf_msg.Uhf.uhf_response queryResponse, BasicReaderCommand command) {
        int status = queryResponse.getStatus();
        log.error("发送{}指令@InventQuery时出错,Termination--->ip:{},天线接口:{},返回状态:{}",getOperation(command),ip,antId,status);
    }

    protected void handlerRepeat1(String ip, int antId, uhf_msg.Uhf.uhf_response queryResponse, BasicReaderCommand command) {
        log.error("发送{}指令@InventRepeat时出错,NEXT:@InventRepeat--->ip:{},天线接口:{},返回状态:1",getOperation(command),ip,antId);
    }

    /**
     * repeat正确结束
     * */
    protected void handlerRepeat2(String ip, int antId, uhf_msg.Uhf.uhf_response queryResponse, BasicReaderCommand command) {
//        log.info("{}指令@InventRepeat正确,End--->ip:{},天线接口:{},返回状态:2",getOperation(command),ip,antId);
    }

    protected void handlerRepeatOther(String ip, int antId, uhf_msg.Uhf.uhf_response queryResponse, BasicReaderCommand command) {
        int status = queryResponse.getStatus();
        log.error("发送{}指令@InventRepeat时出错,Termination--->ip:{},天线接口:{},返回状态:{}",getOperation(command),ip,antId,status);
    }

    protected void handlerRecvTimeout(String ip, BasicReaderCommand command) {
        log.error("发送{}指令,接收响应时超时,Termination--->ip:{}",getOperation(command),ip);
    }

    public void execute(IReaderChannel channel, Rd30Configuration configuration, BasicReaderCommand command) {
        final Uhf.uhf_request request = inventRequest(configuration);
        byte[] recv = channel.sendRecv(request.toByteArray());
        if (recv != null) {
            uhf_msg.Uhf.uhf_response queryResponse = null;
            try {
                queryResponse = uhf_msg.Uhf.uhf_response.parseFrom(recv);
            } catch (InvalidProtocolBufferException e) {
                throw new RuntimeException("protoc不正确");
            }
            int status = queryResponse.getStatus();
            if (status == 0) {
                handlerOperation(channel,queryResponse,request.getEpcQuery().getAntId(),command);
                inventRepeat(channel,request.getEpcQuery().getAntId(),command);
            } else if (status == 1) {
                handlerQuery1(channel.getIp(),request.getEpcQuery().getAntId(),queryResponse,command);
                inventRepeat(channel,request.getEpcQuery().getAntId(),command);
            } else if (status == 2) {
                handlerQuery2(channel.getIp(),request.getEpcQuery().getAntId(),queryResponse,command);
            } else {
                handlerQueryOther(channel.getIp(),request.getEpcQuery().getAntId(),queryResponse,command);
            }
        } else {
            handlerRecvTimeout(channel.getIp(),command);
        }
    }


    /**
     * 清点请求
     */
    private uhf_msg.Uhf.uhf_request inventRequest(Rd30Configuration configuration) {
        Random random = new Random();
        int freq = configuration.getFreqs()[random.nextInt(configuration.getFreqs().length)];
        int antId = configuration.getAnts()[random.nextInt(configuration.getAnts().length)];
        uhf_msg.Uhf.uhf_request request = uhf_msg.Uhf.uhf_request.getDefaultInstance();
        request = request.toBuilder()
                .setType(uhf_msg.Uhf.uhf_request.HeadType.epcInvent)
                .setEpcQuery(
                        uhf_msg.Uhf.uhf_request.EpcQueryPara.newBuilder()
                                .setAntId(antId)
                                .setCodeType(configuration.getCodeType())
                                .setForwardModulation(3)
                                .setForwardRate(configuration.getForwardRate())
                                .setFreq(freq)
                                .setPower(configuration.getPower())
                                .setReverseRate(configuration.getReverseRate())
                                .setTagNum(1)
                                .build())
                .build();
        return request;
    }

    /**
     * repeat执行
     */
    private void inventRepeat(IReaderChannel channel, Integer antId, BasicReaderCommand command) {
        uhf_msg.Uhf.uhf_request requestRepeat = repeatRequest();
        byte[] recv = channel.sendRecv(requestRepeat.toByteArray());
        if (recv != null) {
            uhf_msg.Uhf.uhf_response repeatResponse = null;
            try {
                repeatResponse = uhf_msg.Uhf.uhf_response.parseFrom(recv);
            } catch (InvalidProtocolBufferException e) {
                throw new RuntimeException("protoc不正确");
            }
            int repeatStatus = repeatResponse.getStatus();
            if (repeatStatus == 0) {
                handlerOperation(channel,repeatResponse, antId, command);
                inventRepeat(channel, antId, command);
            } else if (repeatStatus == 1) {
                handlerRepeat1(channel.getIp(),antId,repeatResponse,command);
                inventRepeat(channel, antId, command);
            } else if(repeatStatus == 2){
                handlerRepeat2(channel.getIp(),antId,repeatResponse,command);
            }else{
                handlerRepeatOther(channel.getIp(),antId,repeatResponse,command);
            }
        } else {
            handlerRecvTimeout(channel.getIp(),command);
        }
    }

    /**
     * repeat请求
     */
    private uhf_msg.Uhf.uhf_request repeatRequest() {
        uhf_msg.Uhf.uhf_request request = uhf_msg.Uhf.uhf_request.getDefaultInstance();
        request = request.toBuilder()
                .setType(uhf_msg.Uhf.uhf_request.HeadType.epcQueryRepeat)
                .build();
        return request;
    }

    private String getOperation(BasicReaderCommand command){
        if(command instanceof InventoryCommand){
            return "清点";
        }else if(command instanceof ReadCommand){
            return "读取";
        }else if(command instanceof WriteCommand){
            return "写";
        }else if(command instanceof LockCommand){
            return "锁";
        }else{
            return "未知";
        }
    }

    protected void response(Object arg) {
        this.setChanged();
        this.notifyObservers(arg);
    }
}
